package com.example.wac.interceptor;

import cn.hutool.core.lang.UUID;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.wac.annotation.AvoidResubmit;
import com.example.wac.enums.ErrorCode;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

/**
 * @author wuancheng
 * @description 防重复提交环绕通知
 * @date 2022-05-09 19:13:00
 */

@Component
@Aspect
public class ResubmitAspect {
    @Autowired
    RedisTemplate redisTemplate;

    @Pointcut("@annotation(com.example.wac.annotation.AvoidResubmit)")
    public void pointCut(){}

    @Around("pointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        Object[] args = joinPoint.getArgs();
        String md5Args = SecureUtil.md5(JSONObject.toJSONString(args));
        MethodSignature signature =(MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String className = method.getDeclaringClass().getName();
        String methodName = method.getName();
        String key = String.format("%s:%s:%s", className, methodName, md5Args);
        AvoidResubmit annotation = method.getAnnotation(AvoidResubmit.class);
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, UUID.randomUUID(), annotation.timeOut(), TimeUnit.SECONDS);
        if (!flag){
            throw  ErrorCode.FREQUENT_OPERATIONS.getAppException();
        }
        return joinPoint.proceed();
    }
}
